package com.codrim.cs.data.server.rpc;

import com.alibaba.dubbo.config.annotation.Service;
import com.codrim.common.utils.exception.Assert;
import com.codrim.common.utils.web.vo.PagingResult;
import com.codrim.cs.data.rpc.ConversionsService;
import com.codrim.cs.data.rpc.dto.param.AffiliateConversionParamDTO;
import com.codrim.cs.data.rpc.dto.result.ConversionDTO;
import com.codrim.cs.data.server.dao.entity.ConversionDO;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import static org.springframework.data.mongodb.core.query.Query.query;

/**
 * Created by Liang.Zhuge on 19/10/2017.
 */
@Service(version = ConversionsService.RPC_VERSION)
public class ConversionsServiceImpl implements ConversionsService {
    private static final Logger logger = LoggerFactory.getLogger(ConversionsServiceImpl.class);

    @Resource MongoTemplate mongoTemplate;

    @Override
    public PagingResult<ConversionDTO> conversionsForAffiliate(AffiliateConversionParamDTO param) {
        logger.info("Param:{}", param);

        final Date begin = param.getBegin();
        final Date end = param.getEnd();
        final Integer companyId = param.getCompanyId();

        Assert.notNull(begin, "Begin can not be null");
        Assert.notNull(end, "End can not be null");
        Assert.notNull(companyId, "Company id can not be null");

        logger.info("Conversions for affiliate, param:{}, sZone:{}", param);
        String sEnd = DateFormatUtils.format(end, "yyyyMMdd") + "235959";
        String sBegin = DateFormatUtils.format(begin, "yyyyMMdd") + "000000";
        Criteria where = Criteria.where("convertDate")
                .gte(sBegin)
                .lte(sEnd)
                .and("affId").is(String.valueOf(companyId))
                .and("scrubStatus").is(0);

        List<Integer> affIds = param.getAdvertiserIds();
        if (CollectionUtils.isNotEmpty(affIds)) {
            where = where.and("advId").in(affIds);
        }

        List<Integer> offerIds = param.getOfferIds();
        if (CollectionUtils.isNotEmpty(offerIds)) {
            where = where.and("offerId").in(offerIds.stream().map(String::valueOf).collect(Collectors.toList()));
        }

        //转化报表权限
        Set<Integer> affAdvertiserManagerIdForPermissionSet = param.getAffAdvertiserManagerIdForPermissionSet();
        if(CollectionUtils.isNotEmpty(affAdvertiserManagerIdForPermissionSet)){
            where = where.and("affAdvertiserManagerId").in(affAdvertiserManagerIdForPermissionSet);
        }
        logger.info("where: {}", where);

        final long count = mongoTemplate.count(query(where), ConversionDO.class);

        PagingResult<ConversionDTO> result = new PagingResult<>();
        result.setTotal((int) count);

        if (count > 0) {
            final int skip = param.getPage() <= 1 ? 0 : (param.getPage() - 1) * param.getRows();
            final Query limit = query(where)
                    .with(new Sort(Sort.Direction.DESC, "convertDate"))
                    .skip(skip)
                    .limit(param.getRows());
            final List<ConversionDTO> rows = Optional.ofNullable(mongoTemplate.find(limit, ConversionDO.class))
                    .map(cs -> cs.stream().map(ConversionDO::toDTO).collect(Collectors.toList()))
                    .orElse(null);
            result.setRows(rows);
        }
        return result;
    }
}
